/**
 * 
 */
package info.niwota.web.util;

import info.niwota.web.Debug;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.TextArea;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.ByteArrayOutputStream;
import java.io.FileWriter;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;

import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.WindowConstants;

/**
 * @author qiangli
 * 
 */

public class ConsoleFrame extends JFrame implements WindowListener, ActionListener {

	private static final long serialVersionUID = 1L;

	private String logfile;

	private PrintStream printStream = new PrintStream(new TeeFilterOutputStream(
			new ByteArrayOutputStream()));

	private TextArea contentArea = new TextArea();

	private boolean isLogging = true;

	public ConsoleFrame(String logfile, int width, int height, boolean visible) {
		
		this.logfile = logfile;

		Container c = getContentPane();
		setTitle("Console");
		
		setSize(width, height);
		c.setLayout(new BorderLayout());
		c.add("Center", contentArea);
		
		contentArea.setEditable(false);
		//
		createMenumar();
		//
		center(width, height);
		setVisible(visible);
		requestFocus();

		System.setOut(printStream);
		System.setErr(printStream);

		setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);

		Toolkit tk = Toolkit.getDefaultToolkit();
		Image im = tk.getImage("/res/drawable/icon16.gif");
		setIconImage(im);
		
	}

	private void center(int width, int height) {
		Dimension dim = getToolkit().getScreenSize();
		setLocation((dim.width - width) / 2, (dim.height - height) / 2);
		setSize(width, height);
	}

	private void createMenumar() {
		JMenuBar menubar = new JMenuBar();
		JMenu menu1 = new JMenu("Menu");
		JMenuItem clearItem = new JMenuItem("Clear log");
		JMenuItem closeItem = new JMenuItem("Close");
		closeItem.addActionListener(this);
		clearItem.addActionListener(this);
		closeItem.setActionCommand("close");
		clearItem.setActionCommand("clear");
		
		menu1.add(clearItem);
		menu1.addSeparator();
		menu1.add(closeItem);
		
		JMenu menu2 = new JMenu("Debug");
		ButtonGroup group = new ButtonGroup();
		JRadioButtonMenuItem offItem = new JRadioButtonMenuItem("Off");
		JRadioButtonMenuItem infoItem = new JRadioButtonMenuItem("Info");
		JRadioButtonMenuItem debugItem = new JRadioButtonMenuItem("Debug");
		JRadioButtonMenuItem traceItem = new JRadioButtonMenuItem("Trace");
		offItem.addActionListener(this);
		infoItem.addActionListener(this);
		debugItem.addActionListener(this);
		traceItem.addActionListener(this);
		
		offItem.setActionCommand("debug.off");
		infoItem.setActionCommand("debug.i");
		debugItem.setActionCommand("debug.d");
		traceItem.setActionCommand("debug.t");
		
		infoItem.setSelected(true);
		Debug.setInfo();
		
		group.add(offItem);
		group.add(infoItem);
		group.add(debugItem);
		group.add(traceItem);
		
		menu2.add(offItem);
		menu2.add(infoItem);
		menu2.add(debugItem);
		menu2.add(traceItem);
		
		menubar.add(menu1);
		menubar.add(menu2);
		
		setJMenuBar(menubar);
	}

	private class TeeFilterOutputStream extends FilterOutputStream {
		FileWriter w = null;

		public TeeFilterOutputStream(OutputStream os) {
			super(os);

			if (logfile != null) {
				try {
					w = new FileWriter(logfile, true);
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		public void write(int b) throws IOException {
			if (!isLogging) {
				return;
			}
			String s = ((byte) b) + "";
			contentArea.append(s);
			if (w != null) {
				w.write(s);
				w.flush();
			}
		}

		public void write(byte b[]) throws IOException {
			if (!isLogging) {
				return;
			}
			write(b, 0, b.length);
		}

		public void write(byte b[], int off, int len) throws IOException {
			if (!isLogging) {
				return;
			}
			String s = new String(b, off, len);
			contentArea.append(s);
			if (w != null) {
				w.write(s);
				w.flush();
			}
		}

		public void close() {
			try {
				if (w != null) {
					w.close();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}

			try {
				super.close();
			} catch (IOException e) {
				e.printStackTrace();
			}

		}
	}

	@Override
	public void windowActivated(WindowEvent arg0) {
	}

	@Override
	public void windowClosed(WindowEvent arg0) {
		isLogging = false;
	}

	@Override
	public void windowClosing(WindowEvent arg0) {
	}

	@Override
	public void windowDeactivated(WindowEvent arg0) {
	}

	@Override
	public void windowDeiconified(WindowEvent arg0) {
		isLogging = true;
	}

	@Override
	public void windowIconified(WindowEvent arg0) {
		isLogging = false;
	}

	@Override
	public void windowOpened(WindowEvent arg0) {
		isLogging = true;
	}

	@Override
	public void actionPerformed(ActionEvent evt) {
		final String act =  evt.getActionCommand();
		if (act == null) {
			return;
		}
		if (act.equals("close")) {
			setVisible(false);
		} else if (act.equals("clear")) {
			contentArea.setText(null);
		} else if (act.equals("debug.off")) {
			isLogging = false;
			Debug.setOff();
		} else if (act.equals("debug.i")) {
			isLogging = true;
			Debug.setInfo();
		} else if (act.equals("debug.d")) {
			isLogging = true;
			Debug.setDebug();
		} else if (act.equals("debug.t")) {
			isLogging = true;
			Debug.setTrace();
		}
	}

}
